首页 > 试题广场 >

滑动窗口的最大值

[编程题]滑动窗口的最大值
  • 热度指数:581493 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解
给定一个长度为 n 的数组 num 和滑动窗口的大小 size ,找出所有滑动窗口里数值的最大值。

例如,如果输入数组{2,3,4,2,6,2,5,1}及滑动窗口的大小3,那么一共存在6个滑动窗口,他们的最大值分别为{4,4,6,6,6,5}; 针对数组{2,3,4,2,6,2,5,1}的滑动窗口有以下6个: {[2,3,4],2,6,2,5,1}, {2,[3,4,2],6,2,5,1}, {2,3,[4,2,6],2,5,1}, {2,3,4,[2,6,2],5,1}, {2,3,4,2,[6,2,5],1}, {2,3,4,2,6,[2,5,1]}。

窗口大于数组长度或窗口长度为0的时候,返回空。

数据范围: ,数组中每个元素的值满足 
要求:空间复杂度 ,时间复杂度


示例1

输入

[2,3,4,2,6,2,5,1],3

输出

[4,4,6,6,6,5]
示例2

输入

[9,10,9,-7,-3,8,2,-6],5

输出

[10,10,9,8]
示例3

输入

[1,2,3,4],5

输出

[]
推荐
import java.util.*;
/**
用一个双端队列,队列第一个位置保存当前窗口的最大值,当窗口滑动一次
1.判断当前最大值是否过期
2.新增加的值从队尾开始比较,把所有比他小的值丢掉
*/
public class Solution {
   public ArrayList<Integer> maxInWindows(int [] num, int size)
    {
        ArrayList<Integer> res = new ArrayList<>();
       	if(size == 0) return res;
		int begin;	
		ArrayDeque<Integer> q = new ArrayDeque<>();
		for(int i = 0; i < num.length; i++){
			begin = i - size + 1;
			if(q.isEmpty())
				q.add(i);
			else if(begin > q.peekFirst())
                q.pollFirst();
		
			while((!q.isEmpty()) && num[q.peekLast()] <= num[i])
                q.pollLast();
			q.add(i);	
			if(begin >= 0)
				res.add(num[q.peekFirst()]);
		}
		return res;
    }
}

编辑于 2015-09-02 14:11:26 回复(51)
class Solution:
    def maxInWindows(self,num:List[int],size:int) -> List[int]:
        res = []

        if size<= len(num) and size!= 0:

            first_max_index = size - 1
           
            second_max_index = size - 1
            # 第一个区域的最大值
            for i in range(size - 1):
                # 更新
                if num[i]>num[first_max_index]:
                    second_max_index = first_max_index
                    first_max_index = i
                elif (num[i] >= num[second_max_index]) and (i > first_max_index):
                    second_max_index = i
               
            res.append(num[first_max_index])

            # 遍历后续数组元素
            for i in range(size,len(num)):
                if first_max_index< i - size + 1:
                    first_max_index = second_max_index
               
                # 判断是否是现在加入最大的元素
                if num[i]>num[first_max_index]:
                    second_max_index = first_max_index
                    first_max_index = i
                elif (num[i]>num[second_max_index]) and (i>first_max_index):
                    second_max_index = i

                # 如果两个最大指向同个下表,那么需要更新下第二大的下标
                if first_max_index == second_max_index:
                    temp_max_index = i
                    for j in range(second_max_index+1,i):
                        if num[j]>num[i] and num[j]>num[temp_max_index]:
                            temp_max_index = j
                   
                    second_max_index = temp_max_index        

                res.append(num[first_max_index])
               
        return res
发表于 2023-03-11 14:59:16 回复(0)
发表于 2022-07-08 22:25:50 回复(0)
class Solution:
    def maxInWindows(self , num: List[int], size: int) -> List[int]:
        if size == 0:
            return None
        if size > len(num):
            return None
        stack = []
        for i in range(len(num)-size+1):
            stack.append(max(num[i:i+size]))
        return stack
有没有大佬帮看下哪里有问题?
发表于 2022-07-04 20:52:51 回复(0)
class Solution:
    def maxInWindows(self , num: List[int], size: int) -> List[int]:
        # write code here
        i=0
        res_list=[]
        while i+size<=len(num):
            max_value=max(num[i:i+size])
            res_list.append(max_value)
            i+=1
        return res_list

如何不超时间

发表于 2022-06-08 16:47:49 回复(1)
class Solution:
    def maxInWindows(self , num: List[int], size: int) -> List[int]:
        # write code here
        q = []  # 构造双端队列存储单调递减的序列,q中元素为序列的索引
        res = [] # 记录结果
        for i in range(len(num)):
            # i 记录窗口右边界
            # 若 q的最大值(队头)在窗口之外,队头出队
            if len(q) != 0 and (i - q[0] + 1) > size:
                q.pop(0)
            # 将滑动到的新元素加入队尾
            while len(q) != 0 and num[i] >= num[q[-1]]:
                q.pop()
            q.append(i)
            # 当i遍历到第一个窗口的长度时,开始记录答案
            if i >= size -1:
                res.append(num[q[0]])
        return res

发表于 2022-05-29 15:32:50 回复(0)

双端队列
时间复杂度:O(n) 空间复杂度:O(k) k为窗口大小

class Solution:
    def maxInWindows(self , num: List[int], size: int) -> List[int]:
        res = []
        dq = []
        for i in range(len(num)):
            while dq and num[dq[-1]] < num[i]:
                dq.pop()
            dq.append(i)
            if i - dq[0] >= size:
                dq.pop(0)
            if i + 1 >= size:
                res.append(num[dq[0]])
        return res
发表于 2022-05-17 20:16:42 回复(0)
数据范围: 1sizen10000

这个用例有九万多个数,和题目要求不符,一直超时,有人做过了么……
运行超时
运行超时:您的程序未能在规定时间内运行结束,请检查是否循环有错或算法复杂度过大。
10/21 组用例通过
运行时间2001ms
占用内存4900KB

发表于 2022-04-02 18:00:32 回复(0)

class Solution:
    def maxInWindows(self , num: List[int], size: int) -> List[int]:
        ans = []
        stack = []
        right = 0
        while right < len(num):
            val = num[right]
            while stack and right - stack[0] + 1 > size:stack.pop(0)
            while stack and num[stack[-1]] < val:stack.pop()
            stack.append(right)
            if right >= size - 1:
                ans.append(num[stack[0]])
            right += 1
        return ans

发表于 2022-03-29 14:44:49 回复(0)

看到题目最直观的想法是:根据num和size可以确认最大值数组的规模,然后对每个窗格的最大值进行求解。然而本题有时间复杂度的要求,所以我们应该尽可能复用之前最大值的结果。

经过简单思考我们可以知道,窗格中的最大值满足以下特征:

  1. 之前的最大值很可能再次成为最大值
  2. 某个最大值会随着窗格离开这个最大值而无法继续成为最大值,越先成为最大值,越早失去成为最大值的资格(先进先出,满足队列的要求)
  3. 窗格每次移动一个位置,新加入窗格的数字和最大值需要进行比较,如果新进入窗格的元素数值大于原来的最大值,那么原来的最大值彻底失去成为最大值的可能:有更新且更大的最大值出现

基于上述思考,我们可以得到代码

class Solution:
    def maxInWindows(self , num: List[int], size: int) -> List[int]:
        # write code here
        q = [] # store max index
        res = [] # store result
        for i in range(len(num)):
            while len(q) and i - q[0] >= size: # clear old max index
                q.pop(0)
            while len(q) and num[q[len(q) - 1]] < num[I]: # clear small max num
                q.pop()
            q.append(i)
            if i >= size - 1: # is time to get result
                res.append(num[q[0]])
        return res
发表于 2022-03-19 10:18:18 回复(0)
class Solution:
    def maxInWindows(self , num: List[int], size: int) -> List[int]:
        # write code here
        # 不满足条件时为空
        if size==0&nbs***bsp;len(num)<size:
            return []
        # 可以生成的组数
        groups=len(num)+1-size
        res=[]
        for i in range(groups):
            # i:size+i保证每次取size个大小
            res.append(max(num[i:size+i]))
        return res

发表于 2022-03-14 10:41:41 回复(0)
res = []
        if size == 0 or size > len(num):
            return res
        for i in range(len(num) - size + 1):
            res.append(max(num[i: i+ size]))
        return res
发表于 2022-03-13 20:21:49 回复(0)
class Solution:
    def maxInWindows(self , num: List[int], size: int) -> List[int]:
        # write code here
        a=[]
        if not size:
            return a
        if len(num)<size:
            return a
        for i in range(len(num)-size+1):
            a.append(max(num[i:i+size]))
        return a

发表于 2021-12-31 16:38:05 回复(0)